/*
 * BooleanObject.java - ScriptME
 * 
 * Copyright (c) 2009 Cesar Henriques <cesar at alttab.com.ar>.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Based on FESI Project
 * 
 * Contributors:
 * 	Jean-Marc Lugrin - initial API and implementation
 * 	Cesar Henriques <cesar at alttab.com.ar> - J2ME Porting and Extensions
 */
package org.scriptme.ecmascript.data;

import org.scriptme.ecmascript.exceptions.EcmaScriptException;
import org.scriptme.ecmascript.exceptions.ProgrammingError;
import org.scriptme.ecmascript.interpreter.Evaluator;

// TODO: Auto-generated Javadoc
/**
 * Implemements the EcmaScript Boolean singleton.
 */
public class BooleanObject extends BuiltinFunctionObject {

	/**
	 * Instantiates a new boolean object.
	 * 
	 * @param prototype
	 *            the prototype
	 * @param evaluator
	 *            the evaluator
	 */
	private BooleanObject(ESObject prototype, Evaluator evaluator) {
		super(prototype, evaluator, "Boolean", 1);
	}

	// overrides
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.scriptme.ecmascript.data.BuiltinFunctionObject#toString()
	 */
	public String toString() {
		return "<Boolean>";
	}

	// overrides
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.scriptme.ecmascript.data.FunctionPrototype#callFunction(org.scriptme.ecmascript.data.ESObject,
	 *      org.scriptme.ecmascript.data.ESValue[])
	 */
	public ESValue callFunction(ESObject thisObject, ESValue[] arguments)
			throws EcmaScriptException {
		if (arguments.length == 0) {
			return ESBoolean.makeBoolean(false);
		} else {
			return ESBoolean.makeBoolean(arguments[0].booleanValue());
		}
	}

	// overrides
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.scriptme.ecmascript.data.ESObject#doConstruct(org.scriptme.ecmascript.data.ESObject,
	 *      org.scriptme.ecmascript.data.ESValue[])
	 */
	public ESObject doConstruct(ESObject thisObject, ESValue[] arguments)
			throws EcmaScriptException {
		BooleanPrototype theObject = null;
		ESObject bp = evaluator.getBooleanPrototype();
		theObject = new BooleanPrototype(bp, evaluator);
		if (arguments.length > 0) {
			theObject.value = ESBoolean
					.makeBoolean(arguments[0].booleanValue());
		} else {
			theObject.value = ESBoolean.makeBoolean(false);
		}
		return theObject;
	}

	/**
	 * Utility function to create the single Boolean object.
	 * 
	 * @param evaluator
	 *            the Evaluator
	 * @param objectPrototype
	 *            The Object prototype attached to the evaluator
	 * @param functionPrototype
	 *            The Function prototype attached to the evaluator
	 * 
	 * @return the Boolean singleton
	 */
	public static BooleanObject makeBooleanObject(Evaluator evaluator,
			ObjectPrototype objectPrototype, FunctionPrototype functionPrototype) {

		BooleanPrototype booleanPrototype = new BooleanPrototype(
				objectPrototype, evaluator);
		BooleanObject booleanObject = new BooleanObject(functionPrototype,
				evaluator);
		try {
			// For booleanPrototype
			class BooleanPrototypeToString extends BuiltinFunctionObject {
				BooleanPrototypeToString(String name, Evaluator evaluator,
						FunctionPrototype fp) {
					super(fp, evaluator, name, 1);
				}

				public ESValue callFunction(ESObject thisObject,
						ESValue[] arguments) throws EcmaScriptException {
					ESValue v = ((BooleanPrototype) thisObject).value;
					String s = v.toString();
					return new ESString(s);
				}
			}
			class BooleanPrototypeValueOf extends BuiltinFunctionObject {
				BooleanPrototypeValueOf(String name, Evaluator evaluator,
						FunctionPrototype fp) {
					super(fp, evaluator, name, 1);
				}

				public ESValue callFunction(ESObject thisObject,
						ESValue[] arguments) throws EcmaScriptException {
					return ((BooleanPrototype) thisObject).value;
				}
			}

			booleanObject.putHiddenProperty("prototype", booleanPrototype);
			booleanObject.putHiddenProperty("length", new ESNumber(1));

			booleanPrototype.putHiddenProperty("constructor", booleanObject);
			booleanPrototype.putHiddenProperty("toString",
					new BooleanPrototypeToString("toString", evaluator,
							functionPrototype));
			booleanPrototype.putHiddenProperty("valueOf",
					new BooleanPrototypeValueOf("valueOf", evaluator,
							functionPrototype));
		} catch (EcmaScriptException e) {
			e.printStackTrace();
			throw new ProgrammingError(e.getMessage());
		}

		evaluator.setBooleanPrototype(booleanPrototype);

		return booleanObject;
	}
}
